package com.sojson.util.security.springsecurity.service.impl;

import java.io.IOException;
import java.util.Set;

import org.springframework.util.CollectionUtils;

import com.sojson.annotation.Kickout;
import com.sojson.config.exception.TransErrorCode;
import com.sojson.config.exception.TransException;
import com.sojson.util.StringUtil;
import com.sojson.util.security.springsecurity.service.AnnotationService;
import com.sojson.util.token.Token;
import com.sojson.util.token.TokenUtil;

/**
 * SpringSecurity权限注解实现类<BR/>
 * 使用方法: 在方法上加@ss.hasPermi('*')<BR/>
 * ss代表@Service("ss")中的ss<BR/>
 * hasPermi代表Service中的方法名<BR/>
 * ('*')代表参数和内容<BR/>
 * 
 * @author liu
 * @date 2021-04-14
 */
public class AnnotationServiceOnline implements AnnotationService {

    /**
     * 验证用户是否登录
     * 
     * @return
     * @throws IOException
     */
    @Kickout
    @Override
    public boolean login() throws IOException {
        if (!TokenUtil.isLogin()) {
            throw new TransException(TransErrorCode.NOT_LOGIN);
        }

        return true;
    }

    /**
     * 验证用户是否具备某权限
     *
     * @param permission 权限字符串
     * @return 用户是否具备某权限
     * @throws IOException 
     */
    @Kickout
    @Override
    public boolean hasPermi(String permission) throws IOException {
        Token token = TokenUtil.getToken();

        if (!TokenUtil.isLogin(token)) {
            throw new TransException(TransErrorCode.NOT_LOGIN);
        }

        if (StringUtil.isEmpty(permission)) {
            throw new TransException(TransErrorCode.PERMIS_ANNO_PARAM_IS_EMPTY);
        }

        Set<String> permissions = token.getPermissions();
        if (CollectionUtils.isEmpty(permissions)) {
            throw new TransException(TransErrorCode.NOT_USER_PERMISSION, permission);
        }

        return hasPermissions(permissions, permission);
    }

    /**
     * 验证用户是否不具备某权限,与 hasPermi逻辑相反
     *
     * @param permission 权限字符串
     * @return 用户是否不具备某权限
     * @throws IOException 
     */
    @Kickout
    @Override
    public boolean lacksPermi(String permission) throws IOException {
        return !hasPermi(permission);
    }

    /**
     * 验证用户是否具有以下任意一个权限
     *
     * @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表
     * @return 用户是否具有以下任意一个权限
     * @throws IOException 
     */
    @Kickout
    @Override
    public boolean hasAnyPermi(String permission) throws IOException {
        Token token = TokenUtil.getToken();

        if (!TokenUtil.isLogin(token)) {
            throw new TransException(TransErrorCode.NOT_LOGIN);
        }

        if (StringUtil.isEmpty(permission)) {
            throw new TransException(TransErrorCode.PERMIS_ANNO_PARAM_IS_EMPTY);
        }

        Set<String> permissions = token.getPermissions();
        if (CollectionUtils.isEmpty(permissions)) {
            throw new TransException(TransErrorCode.NOT_USER_PERMISSION, permission);
        }

        for (String per : permission.split(PERMISSION_DELIMETER)) {
            if (per != null && hasPermissions(permissions, per)) {
                return true;
            }
        }

        throw new TransException(TransErrorCode.NOT_USER_PERMISSION, permission);
    }

    /**
     * 判断用户是否拥有某个角色
     *
     * @param role 角色字符串
     * @return 用户是否具备某角色
     * @throws IOException 
     */
    @Kickout
    @Override
    public boolean hasRole(String role) throws IOException {
        Token token = TokenUtil.getToken();

        if (!TokenUtil.isLogin(token)) {
            throw new TransException(TransErrorCode.NOT_LOGIN);
        }

        if (StringUtil.isEmpty(role)) {
            throw new TransException(TransErrorCode.PERMIS_ANNO_PARAM_IS_EMPTY);
        }

        Set<String> roles = token.getRoles();
        if (CollectionUtils.isEmpty(roles)) {
            throw new TransException(TransErrorCode.NOT_USER_PERMISSION, role);
        }

        for (String ro : roles) {
            if (SUPER_ADMIN.equals(ro) || ro.equals(StringUtil.trim(role))) {
                return true;
            }
        }

        throw new TransException(TransErrorCode.NOT_USER_PERMISSION, role);
    }

    /**
     * 验证用户是否不具备某角色，与 isRole逻辑相反。
     *
     * @param role 角色名称
     * @return 用户是否不具备某角色
     * @throws IOException 
     */
    @Kickout
    @Override
    public boolean lacksRole(String role) throws IOException {
        return !hasRole(role);
    }

    /**
     * 验证用户是否具有以下任意一个角色
     *
     * @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表
     * @return 用户是否具有以下任意一个角色
     */
    @Kickout
    @Override
    public boolean hasAnyRoles(String roles) {
        // if (StringUtils.isEmpty(roles)) {
        // return false;
        // }
        // LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        // if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) {
        // return false;
        // }
        // for (String role : roles.split(ROLE_DELIMETER)) {
        // if (hasRole(role)) {
        // return true;
        // }
        // }
        return false;
    }

    /**
     * 判断是否包含权限
     *
     * @param permissions 权限列表
     * @param permission  权限字符串
     * @return 用户是否具备某权限
     */
    private boolean hasPermissions(Set<String> permissions, String permission) {
        if (!permissions.contains(ALL_PERMISSION) && !permissions.contains(StringUtil.trim(permission))) {
            throw new TransException(TransErrorCode.NOT_USER_PERMISSION, permission);
        }

        return true;
    }

}